#include "BookmarksDialog.h"

#include "BookmarksManager.h"
#include "BookmarksModel.h"
#include "BookmarkNode.h"

#include "TreeProxyModel.h"

#include <QSettings>
#include <QMenu>
#include <QDebug>

BookmarksDialog::BookmarksDialog(QWidget *parent, BookmarksManager *manager)
    : QDialog(parent)
    , m_bookmarksManager(manager)
{
    setupUi(this);

    tree->setUniformRowHeights(true);
    tree->setSelectionBehavior(QAbstractItemView::SelectRows);
    tree->setSelectionMode(QAbstractItemView::ContiguousSelection);
    tree->setTextElideMode(Qt::ElideMiddle);
    m_bookmarksModel = m_bookmarksManager->bookmarksModel();
    m_proxyModel = new TreeProxyModel(this);
    m_proxyModel->setSortRole(Qt::DisplayRole);

    connect(search, SIGNAL(textChanged(QString)),
            m_proxyModel, SLOT(setFilterFixedString(QString)));
    connect(removeButton, SIGNAL(clicked()), tree, SLOT(removeOne()));

    m_proxyModel->setSourceModel(m_bookmarksModel);
    tree->setModel(m_proxyModel);
    tree->setDragDropMode(QAbstractItemView::InternalMove);
    tree->setExpanded(m_proxyModel->index(0, 0), true);
    tree->setAlternatingRowColors(true);
    QFontMetrics fm(font());
    int header = fm.width(QLatin1Char('m')) * 35;
    tree->header()->resizeSection(0, header);
    header = fm.width(QLatin1Char('m')) * 35;
    tree->header()->resizeSection(1, header);
    header = fm.width(QLatin1Char('m')) * 5;
    tree->header()->resizeSection(2, header);
    tree->header()->setStretchLastSection(true);
    connect(tree, SIGNAL(activated(const QModelIndex&)),
            this, SLOT(open()));
    tree->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(tree, SIGNAL(customContextMenuRequested(const QPoint &)),
            this, SLOT(customContextMenuRequested(const QPoint &)));
    connect(addFolderButton, SIGNAL(clicked()), this, SLOT(newFolder()));
    connect(buttonSort, SIGNAL(clicked()), this, SLOT(sortBookmarks()));
    expandNodes(m_bookmarksManager->bookmarks());
    setAttribute(Qt::WA_DeleteOnClose);

    QSettings settings;
    settings.beginGroup(QLatin1String("websettings"));
    checkOneClickEnabled->setChecked(settings.value(QLatin1String("addBookmarkUseDefaultLocation"), false).toBool());
}

BookmarksDialog::~BookmarksDialog()
{
    QSettings settings;
    settings.beginGroup(QLatin1String("websettings"));
    settings.setValue(QLatin1String("addBookmarkUseDefaultLocation"), checkOneClickEnabled->isChecked());

    if (saveExpandedNodes(tree->rootIndex()))
        m_bookmarksManager->changeExpanded();
}

bool BookmarksDialog::saveExpandedNodes(const QModelIndex &parent)
{
    bool changed = false;
    for (int i = 0; i < m_proxyModel->rowCount(parent); ++i)
    {
        QModelIndex child = m_proxyModel->index(i, 0, parent);
        QModelIndex sourceIndex = m_proxyModel->mapToSource(child);
        BookmarkNode *childNode = m_bookmarksModel->node(sourceIndex);
        bool wasExpanded = childNode->expanded;
        if (tree->isExpanded(child))
        {
            childNode->expanded = true;
            changed |= saveExpandedNodes(child);
        } else
        {
            childNode->expanded = false;
        }
        changed |= (wasExpanded != childNode->expanded);
    }
    return changed;
}

void BookmarksDialog::expandNodes(BookmarkNode *node)
{
    for (int i = 0; i < node->children().count(); ++i)
    {
        BookmarkNode *childNode = node->children()[i];
        if (childNode->expanded)
        {
            QModelIndex idx = m_bookmarksModel->index(childNode);
            idx = m_proxyModel->mapFromSource(idx);
            tree->setExpanded(idx, true);
            expandNodes(childNode);
        }
    }
}

void BookmarksDialog::customContextMenuRequested(const QPoint &pos)
{
    QMenu menu;
    QModelIndex index = tree->indexAt(pos);
    index = index.sibling(index.row(), 0);

    if ( !index.parent().isValid())
        return;

    // Определяем тип узла
    QModelIndex idx = m_proxyModel->mapToSource(index);
    BookmarkNode *node = m_bookmarksManager->bookmarksModel()->node(idx);
    BookmarkNode::Type type = node->type();

    if (index.isValid() && !tree->model()->hasChildren(index) && type==BookmarkNode::Bookmark)
    {
        menu.addAction(tr("Открыть"), this, SLOT(open()));
        menu.addSeparator();
    }

    menu.addAction(tr("Удалить"), tree, SLOT(removeOne()));
    menu.exec(QCursor::pos());
}

void BookmarksDialog::open()
{
    QModelIndex index = tree->currentIndex();
    if (!index.parent().isValid())
        return;
    emit openUrl(index.sibling(index.row(), 1).data(BookmarksModel::UrlRole).toUrl());
}

void BookmarksDialog::sortBookmarks()
{
    static bool order = false;
    tree->setSortingEnabled ( true );
    tree->sortByColumn(0, order ? Qt::DescendingOrder : Qt::AscendingOrder );
    order = !order;
}

void BookmarksDialog::newFolder()
{
    QModelIndex currentIndex = tree->currentIndex();
    QModelIndex idx = currentIndex;
    if (idx.isValid() && !idx.model()->hasChildren(idx))
        idx = idx.parent();
    if (!idx.isValid())
    {
        QModelIndex topmenu = m_bookmarksModel->index( m_bookmarksManager->menu() );
        idx = topmenu;
    }
    else
        idx = m_proxyModel->mapToSource(idx);

    BookmarkNode *parent = m_bookmarksManager->bookmarksModel()->node(idx);
    BookmarkNode *node = new BookmarkNode(BookmarkNode::Folder);
    node->title = tr("Новая папка");
    m_bookmarksManager->addBookmark(parent, node, currentIndex.row() + 1);
}
